package org.farng.mp3.id3;

import org.farng.mp3.InvalidTagException;

import java.io.IOException;
import java.io.RandomAccessFile;


/**
 * Title: Description:  DEPRECATED Copyright:    Copyright (c) 2002 Company:
 *
 * @author Eric Farng`
 * @version $Revision: 1.6 $
 */
public class FrameBodyRVAD extends AbstractID3v2FrameBody {
    /** DOCUMENT ME! */
    byte bytesUsed = 16;

    /** DOCUMENT ME! */
    byte increment = 0;

    /** DOCUMENT ME! */
    long peakBass = 0;

    /** DOCUMENT ME! */
    long peakCenter = 0;

    /** DOCUMENT ME! */
    long peakLeft = 0;

    /** DOCUMENT ME! */
    long peakLeftBack = 0;

    /** DOCUMENT ME! */
    long peakRight = 0;

    /** DOCUMENT ME! */
    long peakRightBack = 0;

    /** DOCUMENT ME! */
    long relativeBass = 0;

    /** DOCUMENT ME! */
    long relativeCenter = 0;

    /** DOCUMENT ME! */
    long relativeLeft = 0;

    /** DOCUMENT ME! */
    long relativeLeftBack = 0;

    /** DOCUMENT ME! */
    long relativeRight = 0;

    /** DOCUMENT ME! */
    long relativeRightBack = 0;

    /**
     * Creates a new FrameBodyRVAD object.
     */
    public FrameBodyRVAD() {
        //        this.increment = 0;
        //        this.bytesUsed = (byte) 0;
        //        this.relativeRight = 0;
        //        this.relativeLeft = 0;
        //        this.peakRight = 0;
        //        this.peakLeft = 0;
        //        this.relativeRightBack = 0;
        //        this.relativeLeftBack = 0;
        //        this.peakRightBack = 0;
        //        this.peakLeftBack = 0;
        //        this.relativeCenter = 0;
        //        this.peakCenter = 0;
        //        this.relativeBass = 0;
        //        this.peakBass = 0;
    }

    public FrameBodyRVAD(FrameBodyRVAD copyObject) {
        super(copyObject);
        this.bytesUsed         = copyObject.bytesUsed;
        this.increment         = copyObject.increment;
        this.peakBass          = copyObject.peakBass;
        this.peakCenter        = copyObject.peakCenter;
        this.peakLeft          = copyObject.peakLeft;
        this.peakLeftBack      = copyObject.peakLeftBack;
        this.peakRight         = copyObject.peakRight;
        this.peakRightBack     = copyObject.peakRightBack;
        this.relativeBass      = copyObject.relativeBass;
        this.relativeCenter    = copyObject.relativeCenter;
        this.relativeLeft      = copyObject.relativeLeft;
        this.relativeLeftBack  = copyObject.relativeLeftBack;
        this.relativeRight     = copyObject.relativeRight;
        this.relativeRightBack = copyObject.relativeRightBack;
    }

    /**
     * Creates a new FrameBodyRVAD object.
     *
     * @param increment DOCUMENT ME!
     * @param bitsUsed DOCUMENT ME!
     * @param relativeRight DOCUMENT ME!
     * @param relativeLeft DOCUMENT ME!
     * @param peakRight DOCUMENT ME!
     * @param peakLeft DOCUMENT ME!
     * @param relativeRightBack DOCUMENT ME!
     * @param relativeLeftBack DOCUMENT ME!
     * @param peakRightBack DOCUMENT ME!
     * @param peakLeftBack DOCUMENT ME!
     * @param relativeCenter DOCUMENT ME!
     * @param peakCenter DOCUMENT ME!
     * @param relativeBass DOCUMENT ME!
     * @param peakBass DOCUMENT ME!
     */
    public FrameBodyRVAD(byte increment, byte bitsUsed, long relativeRight, long relativeLeft, long peakRight, long peakLeft, long relativeRightBack, long relativeLeftBack, long peakRightBack, long peakLeftBack, long relativeCenter, long peakCenter, long relativeBass, long peakBass) {
        this.increment         = increment;
        this.bytesUsed         = (byte) (((bitsUsed - 1) / 8) + 1); // convert to bytes.
        this.relativeRight     = relativeRight;
        this.relativeLeft      = relativeLeft;
        this.peakRight         = peakRight;
        this.peakLeft          = peakLeft;
        this.relativeRightBack = relativeRightBack;
        this.relativeLeftBack  = relativeLeftBack;
        this.peakRightBack     = peakRightBack;
        this.peakLeftBack      = peakLeftBack;
        this.relativeCenter    = relativeCenter;
        this.peakCenter        = peakCenter;
        this.relativeBass      = relativeBass;
        this.peakBass          = peakBass;
    }

    /**
     * Creates a new FrameBodyRVAD object.
     *
     * @param file DOCUMENT ME!
     *
     * @throws IOException DOCUMENT ME!
     * @throws InvalidTagException DOCUMENT ME!
     */
    public FrameBodyRVAD(java.io.RandomAccessFile file)
                  throws IOException, InvalidTagException {
        this.read(file);
    }

    /**
     * DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     */
    public String getIdentifier() {
        return "RVAD";
    }

    /**
     * DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     */
    public int getSize() {
        int size = 2 + (bytesUsed * 4);

        if ((relativeRightBack != 0) || (relativeLeftBack != 0) || (peakRightBack != 0) || (peakLeftBack != 0)) {
            size += (bytesUsed * 4);
        }

        if ((relativeCenter != 0) || (peakCenter != 0)) {
            size += (bytesUsed * 2);
        }

        if ((relativeBass != 0) || (peakBass != 0)) {
            size += (bytesUsed * 2);
        }

        return size;
    }

    /**
     * This method is not yet supported.
     *
     * @throws java.lang.UnsupportedOperationException This method is not yet
     *         supported
     */
    public void equals() {
        /**
         * @todo Implement this java.lang.Object method
         */
        throw new java.lang.UnsupportedOperationException("Method equals() not yet implemented.");
    }

    /**
     * DOCUMENT ME!
     *
     * @param file DOCUMENT ME!
     *
     * @throws IOException DOCUMENT ME!
     * @throws InvalidTagException DOCUMENT ME!
     */
    public void read(RandomAccessFile file)
              throws IOException, InvalidTagException {
        int    size;
        int    offset = 0;
        byte[] buffer;

        size   = readHeader(file);
        buffer = new byte[size];
        file.read(buffer);

        this.increment = buffer[offset++];
        this.bytesUsed = (byte) (((buffer[offset++] - 1) / 8 * 8) + 1);

        for (int i = 0; i < (int) bytesUsed; i++) {
            relativeRight = (relativeRight << 8) + buffer[i + offset];
        }

        offset += bytesUsed;

        for (int i = 0; i < (int) bytesUsed; i++) {
            relativeLeft = (relativeLeft << 8) + buffer[i + offset];
        }

        offset += bytesUsed;

        for (int i = 0; i < (int) bytesUsed; i++) {
            peakRight = (peakRight << 8) + buffer[i + offset];
        }

        offset += bytesUsed;

        for (int i = 0; i < (int) bytesUsed; i++) {
            peakLeft = (peakLeft << 8) + buffer[i + offset];
        }

        offset += bytesUsed;

        if (size > (2 + (bytesUsed * 4))) {
            for (int i = 0; i < (int) bytesUsed; i++) {
                relativeRightBack = (relativeRightBack << 8) + buffer[i + offset];
            }

            offset += bytesUsed;

            for (int i = 0; i < (int) bytesUsed; i++) {
                relativeLeftBack = (relativeLeftBack << 8) + buffer[i + offset];
            }

            offset += bytesUsed;

            for (int i = 0; i < (int) bytesUsed; i++) {
                peakRightBack = (peakRightBack << 8) + buffer[i + offset];
            }

            offset += bytesUsed;

            for (int i = 0; i < (int) bytesUsed; i++) {
                peakLeftBack = (peakLeftBack << 8) + buffer[i + offset];
            }

            offset += bytesUsed;
        }

        if (size > (2 + (bytesUsed * 8))) {
            for (int i = 0; i < (int) bytesUsed; i++) {
                relativeCenter = (relativeCenter << 8) + buffer[i + offset];
            }

            offset += bytesUsed;

            for (int i = 0; i < (int) bytesUsed; i++) {
                peakCenter = (peakCenter << 8) + buffer[i + offset];
            }

            offset += bytesUsed;
        }

        if (size > (2 + (bytesUsed * 10))) {
            for (int i = 0; i < (int) bytesUsed; i++) {
                relativeBass = (relativeBass << 8) + buffer[i + offset];
            }

            offset += bytesUsed;

            for (int i = 0; i < (int) bytesUsed; i++) {
                peakBass = (peakBass << 8) + buffer[i + offset];
            }

            offset += bytesUsed;
        }
    }

    /**
     * DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     */
    public String toString() {
        return increment + " " + (bytesUsed * 8) + " " + // convert back to bits
               relativeRight + " " + relativeLeft + " " + peakRight + " " + peakLeft + " " + relativeRightBack + " " + relativeLeftBack + " " + peakRightBack + " " + peakLeftBack + " " + relativeCenter + " " + peakCenter + " " + relativeBass + " " + peakBass;
    }

    /**
     * DOCUMENT ME!
     *
     * @param file DOCUMENT ME!
     *
     * @throws IOException DOCUMENT ME!
     */
    public void write(RandomAccessFile file)
               throws IOException {
        byte[] buffer;
        int    offset = 0;

        writeHeader(file, this.getSize());

        buffer = new byte[this.getSize()];

        buffer[offset++] = this.increment;
        buffer[offset++] = this.bytesUsed;

        for (int i = 0; i < (int) bytesUsed; i++) {
            buffer[i + offset] = (byte) (relativeRight >> ((bytesUsed - i - 1) * 8));
        }

        offset += this.bytesUsed;

        for (int i = 0; i < (int) bytesUsed; i++) {
            buffer[i + offset] = (byte) (relativeLeft >> ((bytesUsed - i - 1) * 8));
        }

        offset += this.bytesUsed;

        for (int i = 0; i < (int) bytesUsed; i++) {
            buffer[i + offset] = (byte) (peakRight >> ((bytesUsed - i - 1) * 8));
        }

        offset += this.bytesUsed;

        for (int i = 0; i < (int) bytesUsed; i++) {
            buffer[i + offset] = (byte) (peakLeft >> ((bytesUsed - i - 1) * 8));
        }

        offset += this.bytesUsed;

        if ((relativeRightBack != 0) || (relativeLeftBack != 0) || (peakRightBack != 0) || (peakLeftBack != 0)) {
            for (int i = 0; i < (int) bytesUsed; i++) {
                buffer[i + offset] = (byte) (relativeRightBack >> ((bytesUsed - i - 1) * 8));
            }

            offset += this.bytesUsed;

            for (int i = 0; i < (int) bytesUsed; i++) {
                buffer[i + offset] = (byte) (relativeLeftBack >> ((bytesUsed - i - 1) * 8));
            }

            offset += this.bytesUsed;

            for (int i = 0; i < (int) bytesUsed; i++) {
                buffer[i + offset] = (byte) (peakRightBack >> ((bytesUsed - i - 1) * 8));
            }

            offset += this.bytesUsed;

            for (int i = 0; i < (int) bytesUsed; i++) {
                buffer[i + offset] = (byte) (peakLeftBack >> ((bytesUsed - i - 1) * 8));
            }

            offset += this.bytesUsed;
        }

        if ((relativeCenter != 0) || (peakCenter != 0)) {
            for (int i = 0; i < (int) bytesUsed; i++) {
                buffer[i + offset] = (byte) (relativeCenter >> ((bytesUsed - i - 1) * 8));
            }

            offset += this.bytesUsed;

            for (int i = 0; i < (int) bytesUsed; i++) {
                buffer[i + offset] = (byte) (peakCenter >> ((bytesUsed - i - 1) * 8));
            }

            offset += this.bytesUsed;
        }

        if ((relativeBass != 0) || (peakBass != 0)) {
            for (int i = 0; i < (int) bytesUsed; i++) {
                buffer[i + offset] = (byte) (relativeBass >> ((bytesUsed - i - 1) * 8));
            }

            offset += this.bytesUsed;

            for (int i = 0; i < (int) bytesUsed; i++) {
                buffer[i + offset] = (byte) (peakBass >> ((bytesUsed - i - 1) * 8));
            }

            offset += this.bytesUsed;
        }

        file.write(buffer);
    }
}